#include <stdio.h>
#include "bit_array.h"
//#include "luaWrapper.h"
//#include "algo_cmd.h"
#include "CommandLineParser.h"
#include<string.h>
#include <map>
#include <string>
#include <iostream>
#include <luaWrapper.h>

using namespace std;

typedef struct _addr_data_
{
	string name;
	int value;
}addr_data;

map<int, addr_data>  g_map_data;
#ifdef _PLAT_XILINX_
#include "libHJ.h"
#else
int get_HJlib_val(int addr)             //获取对应寄存器的值
{
	map<int, addr_data>::iterator it_data;
	addr_data data;

	it_data = g_map_data.find(addr);

	if (it_data != g_map_data.end())
	{
		return it_data->second.value;
	}

	return 0 ;
}

int set_HJlib_val(int addr, int val)    //设置寄存器的值
{
	map<int, addr_data>::iterator it_data;
	addr_data data;

	it_data = g_map_data.find(addr);

	if (it_data != g_map_data.end())
	{
		it_data->second.value = val;
	}
	else
	{
		data.value = val;
		g_map_data[addr] = data;
	}

	return 0;
}
int open_HJlib()
{
	return 0;
}
int close_HJlib()
{
	return 0;
}
#endif

int get_map_data();
void parseCommandLine(int argc, char** argv);
int write_data_file();

int g_addr = 0;
int g_value = 0;
bool g_bkey_input = 0;
string g_data_file;
string g_key_file = "./app_input.lua";
int g_data_num = 0;
using namespace luacpp;

luacpp::luaWrapper g_key_lua;

static void Usage(CommandLineParser& opt, char* ExeName)
{
	cerr << "Usage: " << ExeName << "-addr <addr> -value <value>" << endl;
	cerr << "Options:" << endl;

	for (auto& command : opt.displayOrder)
		cerr << "  " << opt.descs[command] << endl;
}

int init_map_option(int addr, string name,int value);
int init_map();

int main(int argc, char* argv[])
{
	CBit_arr bit_arr;
	int bytes = 4;
	int idx = 0;
	int i = 0;
	map<int, addr_data>::iterator it_data;
	int value = 0;
	open_HJlib();
	init_map();
	parseCommandLine(argc, argv);
	if (argc > 3)
	{
		if(!g_bkey_input)
			set_HJlib_val(g_addr, g_value);
	}
	else if (argc == 3)
	{
		g_addr = atoi(argv[1]);
		g_value = atoi(argv[2]);
		int ret = set_HJlib_val(g_addr, g_value);
		printf("app set addr %d value %d ret %d.\n", g_addr,g_value, ret);
	}
	else
	{
		get_map_data();
	}

	if (!g_data_file.empty())
	{
		write_data_file();
	}

	if (g_bkey_input)
	{
		luacpp::reg_cfun(g_key_lua, "set_value", set_HJlib_val);
		luacpp::reg_cfun(g_key_lua, "get_value", get_HJlib_val);
		luacpp::reg_cfun(g_key_lua, "exit", exit);
		g_key_lua.dofile(g_key_file.c_str());
		int ret = 0;
		while (true)
		{
			string str;	// 读取整行 回车结束
			getline(cin, str);
			if (strcmp(str.c_str(), "quit") == 0 ||
				strcmp(str.c_str(), "q")==0
				)
			{
				printf("app quit.\n");
				break;
			}

			try
			{
				ret= luacpp::call<int>(g_key_lua, "analysis_key", str);
			}
			catch (std::string& err)
			{
				printf("%s \n", err.c_str());
				return -1;
			}
		}
	}
	
	close_HJlib();
	return 0;
}

int init_map_option(int addr, string name, int value)
{
	addr_data data;

	data.name = name;
	data.value = value;
	g_map_data[addr] = data;

	return 0;
}

int init_map()
{
	init_map_option(0,"pl ctrl",3);

	init_map_option(1, "awb", 0);
	init_map_option(2, "Clahe",2);
	init_map_option(3, "Gamma", 1);
	init_map_option(4, "Usm enhance", 3);
	init_map_option(5, "color temp", 7);

	init_map_option(6, "screen brightness", 50);
	init_map_option(7, "ae", 0);
	init_map_option(8, "light", 128);
	init_map_option(9, "scale", 8);
	init_map_option(0x0a, "usm denoise", 4);

	return 0;
}

int get_map_data()
{
	int value = 0;
	for (auto it : g_map_data)
	{
		int add = it.first;
		string str_tmp = it.second.name;
		value = get_HJlib_val(add);
		printf("%s : %d \n", str_tmp.c_str(), value);
	}
	return 0;
}

void parseCommandLine(int argc, char** argv)
{
	bool help = false;
	auto opt = CommandLineParser();
	opt.addFlag("-help", &help, "Show this help");
	opt.addInt("-addr", &g_addr,   "addr ");
	opt.addInt("-value", &g_value, "value ");
	opt.addString("-dfile",&g_data_file, "data file");
	opt.addInt("-dnum", &g_data_num,"data num");
	opt.addString("-keyfile", &g_key_file, "keyinput mode ");
	opt.addOption("-keydebug", [&](string) {
		g_bkey_input = true;
		}, "key debug"
	);
/*
	opt.addOption("--dma-in,-dma-in", [&](string) {
		settings.bDMAIn = true;
		settings.eDMAIn = OMX_ALG_BUF_DMA;
		}, "use dmabufs for input port");
*/

	for (auto i = 0; i < argc;i++)
	{
		printf("%s ",argv[i]);
	}
	printf("\n");
	opt.parse(argc, argv);

	if (help)
	{
		Usage(opt, argv[0]);
		exit(0);
	}
	return;
}
/*
-addr 5 -value 10
*/

int write_data_file()
{
	char buf[1024];
	int value = 0;
	int line = 0;
	int addr = g_addr;
	int ret = 0;
	int write_num = 0xFFFFFF;
	if (g_data_num != 0)
	{
		write_num = g_data_num;
	}
	FILE* pDataFile = fopen(g_data_file.c_str(), "r");
	if (pDataFile == NULL)
	{
		return -1;
	}
	printf(" write date start addr %d write_num %d .\n",addr, write_num);
	while (fgets(buf, sizeof(buf), pDataFile) != NULL)
	{
		line++;
		if (strlen(buf) == 0)
		{
			printf("line %d is empty.\n",line);
			continue;
		}
		value = atoi(buf);
		ret = set_HJlib_val(addr,value);
		addr++;
		if (--write_num <= 0)
		{
			break;
		}
	}
	printf("write data end  count %d .\n ",line);
	return 0;
}